package com.better.frontend.service.paper;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.better.backend.mqReceiverService.calType.model.CalTypeModel;
import com.better.backend.mqReceiverService.calType.repository.CalTypeRepsitory;
import com.better.backend.mqReceiverService.examReceiver.model.ExamModel;
import com.better.backend.mqReceiverService.examReceiver.model.ExamUnitModel;
import com.better.backend.mqReceiverService.examReceiver.model.SubjectScoreModel;
import com.better.backend.mqReceiverService.questionReceiver.model.ExamPaperModel;
import com.better.backend.mqReceiverService.questionReceiver.model.PointPaperModel;
import com.better.backend.mqReceiverService.questionReceiver.model.QuestionModel;
import com.better.backend.mqReceiverService.questionReceiver.repository.ExamPaperRepsitory;
import com.better.common.base.ServiceResponse;
import com.better.common.utils.CmsHttpPostUtil;
import com.better.common.utils.Encodes;
import com.better.common.utils.GlobalUtil;
import com.better.common.utils.ServiceResponseHandle;
import com.better.consist.ExamEnum;
import com.better.frontend.Iservice.paper.PaperService;
import com.better.frontend.repository.exam.ExmpRepsitory;
import com.better.frontend.vo.studentScore.KnowledgeScoreVo;
import com.better.frontend.vo.studentScore.KnowledgeSeries;
import com.better.util.excelUtil.ImportExcel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.better.consist.CalTypeEnum;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 编辑试卷Service层
 * Created by xq on 2017/11/11.
 */
@Service
public class PaperServiceImp implements PaperService {
    @Resource
    private ExmpRepsitory exmpRepsitory;

    @Resource
    private ExamPaperRepsitory examPaperRepsitory;

    @Resource
    private CalTypeRepsitory calTypeRepsitory;

    @Value("${pointUrl}")
    private String pointUrl;

    /**
     * 保存试卷，如果存在则更新该试卷，否则新增
     * @param paperModel
     * @param excelFile
     */
    @Override
    public ServiceResponse savePaper(ExamPaperModel paperModel, MultipartFile excelFile) {
        try {
            //更新考试对应科目的是否编辑状态
            ExamModel examModel = exmpRepsitory.findOne(paperModel.getExamid());
            if(examModel==null||!ExamEnum.EXAM_STATUS_PAPER.getCode().toString().equals(examModel.getStatus())){
                return ServiceResponseHandle.failed("导入失败！请联系管理员，当前考试信息状态有误。");
            }
            //校级考试
            if(CalTypeEnum.examtype_school.equals(examModel.getExamType())){
                List<ExamUnitModel> examUnitModels = examModel.getExamUnitModels();
                String gId = paperModel.getGradeid();
                String sId = paperModel.getSubjectid();
                examUnitModels = examUnitModels.stream().filter(a -> Objects.nonNull(a)).filter(e->gId.equals(e.getUnitId())).collect(Collectors.toList());
                if(examUnitModels==null||examUnitModels.size()!=1){
                    return ServiceResponseHandle.failed("导入失败！未查询到当前考试对应的年级信息。");
                }
                List<SubjectScoreModel> subjectScoreModels = examUnitModels.get(0).getSubjectScoreModels();
                subjectScoreModels = subjectScoreModels.stream().filter(a->Objects.nonNull(a)).filter(f -> sId.equals(f.getSubjectid())).collect(Collectors.toList());
                if(subjectScoreModels==null||subjectScoreModels.size()!=1){
                    return ServiceResponseHandle.failed("导入失败！为查询到当前考试年级对应的科目信息。");
                }
                if(ExamEnum.PAPER_STATUS_EDIT.getCode().toString().equals(subjectScoreModels.get(0).getIsEdit())){
                    subjectScoreModels.get(0).setIsEdit(ExamEnum.PAPER_STATUS_FINISH.getCode().toString());
                    //exmpRepsitory.save(examModel);
                }
            }
            else{
                //班级考试
                if(!paperModel.getGradeid().equals(examModel.getGradeId())){
                    return ServiceResponseHandle.failed("导入失败！为查询到当前考试对应的年级信息。");
                }
                List<ExamUnitModel> examUnitModels = examModel.getExamUnitModels();
                if(examUnitModels==null||examUnitModels.size()!=1){
                    return ServiceResponseHandle.failed("导入失败！为查询到当前考试对应的年级信息。");
                }
                String sId = paperModel.getSubjectid();
                List<SubjectScoreModel> subjectScoreModels = examUnitModels.get(0).getSubjectScoreModels();
                subjectScoreModels = subjectScoreModels.stream().filter(a -> Objects.nonNull(a)).filter(f->sId.equals(f.getSubjectid())).collect(Collectors.toList());
                if(subjectScoreModels==null||subjectScoreModels.size()!=1){
                    return ServiceResponseHandle.failed("导入失败！为查询到当前考试年级对应的科目信息。");
                }
                if(ExamEnum.PAPER_STATUS_EDIT.getCode().toString().equals(subjectScoreModels.get(0).getIsEdit())){
                    subjectScoreModels.get(0).setIsEdit(ExamEnum.PAPER_STATUS_FINISH.getCode().toString());
                    //exmpRepsitory.save(examModel);
                }
            }

            ServiceResponse pSer =  CmsHttpPostUtil.HttpsGet(pointUrl + "gradeId="+paperModel.getGradeid()+"&subjectId="+paperModel.getSubjectid(), new HashMap<>(16));
            if(!pSer.isSuccess()){
                return ServiceResponseHandle.failed("保存失败!获取知识点有误。请联系管理员！");
            }
            JSONArray obj = (JSONArray) pSer.getData();
            Map<String,PointPaperModel> poList = new HashMap<>();
            if(obj==null||obj.size()==0){
                return ServiceResponseHandle.failed("保存失败!获取知识点有误。请联系管理员！");
            }
            else{
               for (int i = 0;i<obj.size();i++){
                   PointPaperModel p = new PointPaperModel();
                   p.setPointId(obj.getJSONObject(i).getString("id"));
                   p.setPointName(obj.getJSONObject(i).getString("knowName"));
                   String k = Encodes.md5(p.getPointName());
                   poList.put(k,p);
               }
            }
            ImportExcel importExcel = new ImportExcel(excelFile, 0, 0);
            //生成题目信息
            List<QuestionModel> questionModelList = importExcel.getQues(poList);
            //验证小题总分
            BigDecimal allScore = questionModelList.stream().map(QuestionModel::getDeciScore).reduce(BigDecimal.ZERO, BigDecimal::add);
            //获取试卷信息，如果没有则新建，如果存在，则更新
            paperModel = getPaperModel(paperModel);
            if(!allScore.equals(new BigDecimal(paperModel.getToalscore()))){
                return ServiceResponseHandle.failed("导入失败！小题总分和试卷得分不一致");
            }
            paperModel.setQuestionModelList(questionModelList);
            paperModel.setIsEdit(ExamEnum.PAPER_STATUS_FINISH.getCode().toString());
            examPaperRepsitory.save(paperModel);
            exmpRepsitory.save(examModel);
            return ServiceResponseHandle.success(paperModel);
        }
        catch (Exception e){
            //e.printStackTrace();
            return ServiceResponseHandle.failed(e.getLocalizedMessage());
        }
    }


    /**
     * 查询试卷信息信息
     *
     * @author:
     * @date :2017/11/8
     */
    public ServiceResponse selectPaper(ExamPaperModel paperModel){
        String examID = paperModel.getExamid();
        String subId = paperModel.getSubjectid();
        String gradeId = paperModel.getGradeid();
        paperModel = examPaperRepsitory.findByExamidAndSubjectidAndGradeid(examID,subId,gradeId);
        return ServiceResponseHandle.success(paperModel);
    }
    /**
     * 通过考试ID查询，试卷信息
     * @param paperModel
     * @return
     */
    public ExamPaperModel getPaperModel(ExamPaperModel paperModel){
        String examID = paperModel.getExamid();
        String subId = paperModel.getSubjectid();
        String gradeId = paperModel.getGradeid();
        ExamPaperModel reModel = examPaperRepsitory.findByExamidAndSubjectidAndGradeid(examID,subId,gradeId);
        if(reModel==null){
            reModel = new ExamPaperModel();
            ExamModel examModel = exmpRepsitory.findOne(examID);
            reModel.setId(GlobalUtil.createGlobalId());
            reModel.setExamid(examID);
            reModel.setExamname(examModel.getExamName());
            reModel.setSchoolid(examModel.getSchoolId());
            reModel.setSchoolname(examModel.getSchoolName());
            reModel.setGradeid(gradeId);
            reModel.setIsEdit(ExamEnum.PAPER_STATUS_EDIT.getCode().toString());
            ExamUnitModel unitMo = null;
            //设置考试年级信息，班级考试
            if(CalTypeEnum.examtype_class.equals(examModel.getExamType())){
                reModel.setGradename(examModel.getGradeName());
                unitMo = examModel.getExamUnitModels().get(0);
            }
            //校级考试
            else{
                unitMo = examModel.getExamUnitModels().stream().filter(s -> Objects.nonNull(s)).filter(u->u.getUnitId().equals(gradeId)).collect(Collectors.toList()).get(0);
                reModel.setGradename(unitMo.getUnitName());
            }
            //设置总分,科目信息
            List<SubjectScoreModel> l = unitMo.getSubjectScoreModels().stream().filter(s -> Objects.nonNull(s)).filter(s->s.getSubjectid().equals(subId)).collect(Collectors.toList());
           SubjectScoreModel subjectScoreModelList = unitMo.getSubjectScoreModels().stream().filter(s -> Objects.nonNull(s)).filter(s->s.getSubjectid().equals(subId)).collect(Collectors.toList()).get(0);
            reModel.setSubjectid(subId);
            reModel.setSubjectname(subjectScoreModelList.getSubjectname());
            reModel.setToalscore(subjectScoreModelList.getToalscore());
            //更新考试状态
            /*if(ExamEnum.EXAM_STATUS_NEW.getCode().toString().equals(examModel.getStatus())){
                examModel.setStatus(ExamEnum.EXAM_STATUS_PAPER.getCode().toString());
                examModel.setStatusName(ExamEnum.EXAM_STATUS_PAPER.getName());
                exmpRepsitory.save(examModel);
            }*/
        }
        else{
            reModel.setIsEdit(ExamEnum.PAPER_STATUS_EDIT.getCode().toString());
        }
        return reModel;
    }

    /**
     * 通过小题ID设置题目知识点
     * @param pointPaperModels
     * @param quesId
     */
    @Override
    public ServiceResponse savePoint(List<PointPaperModel> pointPaperModels, String quesId,String examID,String subId,String gradeId){
        ExamPaperModel reModel = examPaperRepsitory.findByExamidAndSubjectidAndGradeid(examID,subId,gradeId);
        List<QuestionModel> questionModelList = reModel.getQuestionModelList();
        //查找对应小题信息
        QuestionModel question = questionModelList.stream().filter(s -> Objects.nonNull(s)).filter(q->q.getId().equals(quesId)).collect(Collectors.toList()).get(0);
        //处理知识点，分值比
        boolean isPointSet = setPointRate(pointPaperModels);
        if(!isPointSet){
            return ServiceResponseHandle.failed("保存知识点失败！知识点占比设置有误");
        }
        question.setPointPaperListVo(pointPaperModels);
        //验证是否编辑完成
        if(isEditFinish(reModel)){
            reModel.setIsEdit(ExamEnum.PAPER_STATUS_FINISH.getCode().toString());
        }
        //更新
        examPaperRepsitory.save(reModel);
        return ServiceResponseHandle.success("保存成功");
    }

    /**
     * 新增分析模板
     * @param calTypeModel
     * @return
     */
    public ServiceResponse saveCalType(CalTypeModel calTypeModel){
        CalTypeModel sou = calTypeRepsitory.findByExamId(calTypeModel.getExamId());
        if(sou!=null){
            calTypeModel.setId(sou.getId());
        }
        calTypeModel = calTypeRepsitory.save(calTypeModel);
        return ServiceResponseHandle.success("保存成功");
    }
    /**
     * 根据考试ID，删除本次考试所有已导入的试卷信息
     * @param examId
     * @return
     */
    public void deleteByExamId(String examId){
        List<ExamPaperModel> list = examPaperRepsitory.findByExamid(examId);
        if(list!=null){
            examPaperRepsitory.delete(list);
        }
    }
    /**
     * 通过考试ID，发布试卷
     * @param examID
     * @return
     */
    @Override
    public ServiceResponse publishPaper(String examID){
        List<ExamPaperModel> paperModelList = examPaperRepsitory.findByExamid(examID);
        ExamModel examModel = exmpRepsitory.findOne(examID);
        List<ExamUnitModel> ulist = examModel.getExamUnitModels();
        Integer num = 0;
        for (ExamUnitModel e:ulist) {
            num = num + e.getSubjectScoreModels().size();
        }
        if(paperModelList==null||paperModelList.size()!=num){
            return ServiceResponseHandle.failed("发布失败！还有未编辑完成的试卷");
        }
        //验证每个科目试卷编辑是否完成，完成则发布
        for (ExamPaperModel mo:paperModelList) {
            if(StringUtils.isEmpty(mo.getIsEdit())||ExamEnum.PAPER_STATUS_EDIT.getCode().toString().equals(mo.getIsEdit())){
                return ServiceResponseHandle.failed("发布失败！还有未编辑完成的试卷");
            }
        }
        //更新考试状态
        examModel.setStatus(ExamEnum.EXAM_STATUS_SCORE.getCode().toString());
        examModel.setStatusName(ExamEnum.EXAM_STATUS_SCORE.getName());
        exmpRepsitory.save(examModel);
        return ServiceResponseHandle.success("发布成功");
    }

    /**
     * 验证试卷是否编辑完成
     * @param reModel
     * @return
     */
    public boolean isEditFinish(ExamPaperModel reModel){
        boolean re = true;
        List<QuestionModel> questionModelList = reModel.getQuestionModelList();
        for(int i = 0 ;i<questionModelList.size();i++){
            List<PointPaperModel> list = questionModelList.get(i).getPointPaperListVo();
            if(list==null||list.size()==0){
                re = false;
                return re;
            }
        }
        return re;
    }
    /**
     * 处理知识点分数占比
     * @param pointPaperModels
     */
    public boolean setPointRate(List<PointPaperModel> pointPaperModels){
        boolean re = true;
        //设置有占比的知识点集合
        List<PointPaperModel> haveRate = pointPaperModels.stream().filter(s -> Objects.nonNull(s)).filter(p-> !StringUtils.isEmpty(p.getProportion())).collect(Collectors.toList());
        List<PointPaperModel> noRate = pointPaperModels.stream().filter(s -> Objects.nonNull(s)).filter(p->!haveRate.contains(p)).collect(Collectors.toList());
        if(noRate==null||noRate.size()==0){
            //没有设置分值比的list为空，直接返回数据
            return re;
        }
        else{
            //计算所有已经设置的比
            Integer allRate = haveRate.stream().mapToInt(PointPaperModel::getRate).sum();
            Integer noneRare = 100-allRate;
            if(noRate.size()>noneRare){
                re = false;
                return re;
            }
            BigDecimal[] avgRate = new BigDecimal(noneRare).divideAndRemainder(new BigDecimal(noRate.size()));
            Integer newRare = avgRate[0].intValue();
            Integer mo = avgRate[1].intValue();
            for(int i=0;i<noRate.size();i++){
                Integer sheR = newRare;
                if(mo>0){
                    sheR++;
                    mo--;
                }
                noRate.get(i).setProportion(sheR.toString());
            }
            //设置知识点ID
            pointPaperModels.forEach(p->p.setId(GlobalUtil.createGlobalId()));
        }
        return re;
    }
}
